﻿(function () {
    var numCalc = {
        // 加法
        add: function (arg1, arg2) {
            arg1 = arg1.toString(), arg2 = arg2.toString();
            var arg1Arr = arg1.split("."),
                arg2Arr = arg2.split("."),
                d1 = arg1Arr.length == 2 ? arg1Arr[1] : "",
                d2 = arg2Arr.length == 2 ? arg2Arr[1] : "";
            var maxLen = Math.max(d1.length, d2.length);
            var m = Math.pow(10, maxLen);
            var result = Number(((arg1 * m + arg2 * m) / m).toFixed(maxLen));
            var d = arguments[2];
            return typeof d === "number" ? Number((result).toFixed(d)) : result;
        },
        // 减法
        sun: function (arg1, arg2) {
            return this.add(arg1, -arg2);
        },
        // 乘法
        mul: function (arg1, arg2) {
            var r1 = arg1.toString(),
                r2 = arg2.toString(),
                m, resultVal, d = arguments[2];
            m = (r1.split(".")[1] ? r1.split(".")[1].length : 0) + (r2.split(".")[1] ? r2.split(".")[1].length : 0);
            resultVal = Number(r1.replace(".", "")) * Number(r2.replace(".", "")) / Math.pow(10, m);
            return typeof d !== "number" ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)));
        },
        // 除法
        div: function (arg1, arg2) {
            var r1 = arg1.toString(),
                r2 = arg2.toString(),
                m, resultVal, d = arguments[2];
            m = (r2.split(".")[1] ? r2.split(".")[1].length : 0) - (r1.split(".")[1] ? r1.split(".")[1].length : 0);
            resultVal = Number(r1.replace(".", "")) / Number(r2.replace(".", "")) * Math.pow(10, m);
            return typeof d !== "number" ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)));
        }
    };
    // 定义事件对象标准化函数
    function e(event) {
        // 兼容IE浏览器
        if (!event) {
            event = window.event;
            event.target = event.srcElement;
            event.layerX = event.offsetX;
            event.layerY = event.offsetY;
        }
        // 计算鼠标指针的x轴距离
        event.mx = event.pageX || event.clientX + document.body.scrollLeft;
        // 计算鼠标指针的y轴距离
        event.my = event.pageY || event.clientY + document.body.scrollTop;
        // 返回标准化的事件对象
        return event;
    }
    function CreateUID() {
        var s = [];
        var hexDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = "4";
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
        //s[8] = s[13] = s[18] = s[23] = "-"
        var uuid = s.join("");
        return uuid;
    }

    // 用于保存参数的字典集合
    var ArgDict = {};
    var _plusFiveStar = {
        ToArgs: function (args) {
            var self = _plusFiveStar;
            args = $.extend({
                // 星星评分的数值
                number: 4.5,
                // 总共有几颗星星
                count: 5,
                // 星星的矢量图地址
                star_svg_path: 'src/star-solid.svg',
                // 是否开启编辑功能
                isedit: false,
                // 开启编辑功能所需的参数定义
                edit: {
                    // 编辑时数值的颗粒度设置, 范围在 (0<n<1)
                    particle_size: 0.5,
                    // 编辑需要的事件定义, 值为: ( mousemove | click )
                    event: 'click',
                    // 数值修改触发的更改事件
                    onchange: function (number) {
                        // 在这里写入您的自定义赋值代码
                        console.log('星星评分数值更改为: ', number);
                    },
                },
            }, args);
            if (!args.Id) {
                args.Id = CreateUID();
            }
            ArgDict[args.Id.toString()] = args;
            return args;
        },
        GenerateHTML: function (args) {
            var self = _plusFiveStar;
            var region = $(document.createElement('div'));
            region.addClass('contentStarRegion');
            var count = args.count;
            while (count > 0) {
                var item = self.GenerateItemHTML(args, count > 1 ? 1 : count);
                region.append(item);
                count -= 1;
            }
            return region;
        },
        SetStarShowStyle: function (fiveStarRegionEl, number) {
            var items = fiveStarRegionEl.find('.item');
            for (var i = 0; i < items.length; i++) {
                var itemEl = $(items[i]);
                var rate = 1;
                if (number < 1) {
                    rate = number;
                }
                var css_translate_value = numCalc.sun(1, rate);
                css_translate_value = numCalc.mul(css_translate_value, 100);
                number = numCalc.sun(number, 1);
                number = number < 0 ? 0 : number;
                itemEl.css({
                    'transform': 'translate(-' + css_translate_value + '%, 0)'
                });
                itemEl.find('.icon').css({
                    'transform': 'translate(' + css_translate_value + '%, 0)'
                });
            }
        },
        GenerateItemHTML: function (args, proportion) {
            var self = _plusFiveStar;
            proportion = proportion || 1;

            // 构建html选项内容
            var item = $(document.createElement('div'));
            item.addClass('item');
            var img = $(document.createElement('img'));
            img.addClass('icon');
            img.attr('src', args.star_svg_path);
            img.attr('onload', 'SVGInject(this)');
            item.append(img);
            return item;
        },
        GenerateTouchRegionHTML: function (args) {
            if (!args.isedit) {
                return '';
            }
            var self = _plusFiveStar;
            var div = $(document.createElement('div'));
            div.addClass('TouchRegion');
            div.attr('data-fivestar-id', args.Id);
            switch (args.edit.event) {
                case 'mousemove':
                    div.attr('onmousemove', '_plusFiveStar.MouseMoveEvent.call(this)');
                    break;
                case 'click':
                    div.attr('onclick', '_plusFiveStar.ClickEvent.call(this)');
                default:
                    break;
            }
            return div;
        },
        CalcTouchNumberValue: function(event) {
            var self = _plusFiveStar;
            event = e(event);
            var target = $(event.target);
            var x = event.offsetX;
            var clientWidth = target.width();
            var rate_x = numCalc.div(x, clientWidth);
            rate_x = numCalc.mul(rate_x, 100);
            var id = target.attr('data-fivestar-id');
            var args = ArgDict[id];
            var star_count = args.count;
            var particle_size = args.edit.particle_size;
            var _n = numCalc.div(1, particle_size);
            _n = numCalc.mul(star_count, _n);
            _n = numCalc.div(1, _n);
            var one_start_rate_region = numCalc.mul(_n, 100);
            var number = 0;
            while (rate_x > particle_size) {
                rate_x = numCalc.sun(rate_x, one_start_rate_region);
                number = numCalc.add(number, particle_size);
            }
            return number;
        },
        MouseMoveEvent: function (event) {
            var self = _plusFiveStar;
            event = e(event);
            var target = $(event.target);
            var number = self.CalcTouchNumberValue(event);
            var id = target.attr('data-fivestar-id');
            var args = ArgDict[id];

            self.SetStarShowStyle(target.parents('.ShowValue'), number);
            if (args.edit.onchange) {
                args.edit.onchange(number);
            } else {
                console.log('数值更改为:', number);
            }
        },
        ClickEvent: function (event) {
            var self = _plusFiveStar;
            event = e(event);
            var target = $(event.target);
            var number = self.CalcTouchNumberValue(event);
            var id = target.attr('data-fivestar-id');
            var args = ArgDict[id];

            if (args.number === number) {
                if (number.toString().indexOf('.') > -1) {
                    number = Number(number.toString().split('.')[0]);
                } else {
                    number -= 1;
                }
                args.number = number;
            } else {
                args.number = number;
            }
            ArgDict[id] = args;

            self.SetStarShowStyle(target.parents('.ShowValue'), number);
            if (args.edit.onchange) {
                args.edit.onchange(number);
            } else {
                console.log('数值更改为:', number);
            }
        },
    };
    this._plusFiveStar = {
        Init: function (args) {
            var self = _plusFiveStar;
            args = self.ToArgs(args);
            var region = $(document.createElement('div'));
            region.addClass('fiveStarRegion');

            var show_region = self.GenerateHTML(args);
            show_region.addClass('ShowValue');
            var touch = self.GenerateTouchRegionHTML(args);
            if (touch) {
                show_region.append(touch);
            }
            self.SetStarShowStyle(show_region, args.number);

            var bg_region = self.GenerateHTML(args);
            bg_region.addClass('Background');

            region.append(show_region);
            region.append(bg_region);
            return region[0].outerHTML;
        },
        MouseMoveEvent: _plusFiveStar.MouseMoveEvent,
        ClickEvent: _plusFiveStar.ClickEvent,
    };
})();
